/*
 *	Copyright (C) Ergobyte Informatics S.A. - All Rights Reserved
 *
 * 	This material is proprietary to Ergobyte. The methods and techniques described herein are considered trade secrets
 *	and/or confidential. Reproduction or distribution, in whole or in part, is forbidden except by express written permission.
 */
package com.ergobyte.servo.client;

import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.http.Consts;
import org.apache.http.client.HttpClient;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.AllowAllHostnameVerifier;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.PoolingClientConnectionManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.params.HttpProtocolParams;

public class HttpClientInstance {

	private static final String SCHEME_HTTP = "http";
	private static final String SCHEME_HTTPS = "https";
	private static final int CONNECTION_TIMEOUT = 30 * 000; // 30 seconds
	private static final int SOCKET_TIMEOUT = 60 * 000; // 1 minute

	private static HttpClient httpClient;

	public static HttpClient get() {
		if(httpClient == null) httpClient = createNewHttpClient();
		return httpClient;
	}

	private static HttpClient createNewHttpClient() {
		SchemeRegistry schemeRegistry = new SchemeRegistry();
		schemeRegistry.register(new Scheme(SCHEME_HTTP, 80, PlainSocketFactory.getSocketFactory()));
		schemeRegistry.register(new Scheme(SCHEME_HTTPS, 443, getEasySslSocketFactory()));
		PoolingClientConnectionManager connectionManager = new PoolingClientConnectionManager(schemeRegistry);
		connectionManager.setDefaultMaxPerRoute(5);
		connectionManager.setMaxTotal(10);
		BasicHttpParams httpParams = new BasicHttpParams();
		httpParams.setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, CONNECTION_TIMEOUT);
		httpParams.setIntParameter(CoreConnectionPNames.SO_TIMEOUT, SOCKET_TIMEOUT);
		httpParams.setParameter(HttpProtocolParams.HTTP_CONTENT_CHARSET, Consts.UTF_8);
		DefaultHttpClient client = new DefaultHttpClient(connectionManager, httpParams);
		return client;
	}

	private static SSLSocketFactory easySslSocketFactory;

	private static SSLSocketFactory getEasySslSocketFactory() {
		if(easySslSocketFactory != null) return easySslSocketFactory;
		try {
			TrustManager easyTrustManager = new EasyX509TrustManager();
			SSLContext sslContext = SSLContext.getInstance("SSL");
			sslContext.init(null, new TrustManager[] { easyTrustManager }, new SecureRandom());
			easySslSocketFactory = new SSLSocketFactory(sslContext, new AllowAllHostnameVerifier());
			return easySslSocketFactory;
		}
		catch(Exception e) {
			return easySslSocketFactory = SSLSocketFactory.getSocketFactory();
		}
	}

	private static final class EasyX509TrustManager implements X509TrustManager {

		@Override
		public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
			// Client is trusted, no matter what
		}

		@Override
		public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
			// Server is trusted, no matter what
		}

		@Override
		public X509Certificate[] getAcceptedIssuers() {
			return null;
		}
	}
}
